package scene;

import geometrie.Point;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import Calcule.MemoireCache;
/**
 * Clase pour generer una forme Cone a partir d'un point au milieu,
 * radius et l'hauteur
 * @author Manuel
 * @author Marcos
 */
public class Cone implements Modele3D {
    /** Liste avec des facettes 3D    */
	private List<Facette3D> liste;
	/** Ensamble de points */
	private Point[] points;
	/** Point central du Cone */
	Point pCentral; 
	/** Radius */
	double radius; 
	/** Hauteur */
	double haut; 
	/** Nivel du Complexite */
	int n; 
	
	/**
	 * Constructeur pour generer le Cone
	 * @param pCentral Le point Centrale pour creer la circunference et la pointe
	 * @param radius Radius de la Circunference
	 * @param haut Hauteur de la pointe
	 * @param n Nivel du complexite
	 * @throws Exception "Erreur de taille"
	 */
	public Cone(Point pCentral, double radius, double haut, int n) throws Exception{
		if(n>=3){
			liste = new ArrayList<Facette3D>();	
			this.pCentral = pCentral;
			this.n = n;
			this.radius = radius;
			this.haut = haut;
			creerCone();
		}
		else
			throw new Exception("Erreur de taille: il faut n >= 3");
	
	}
	
	/**
	 * Appeler des methodes pour generer le Cone
	 */
	private void creerCone(){	
		//Generer le tableau de points
		genererPoints();
		//Generer des Facettes 3D a partir des points
		Facette3D[] f = creerFacettes();
		//Ajouter des Facettes a la liste
		for(int i = 0 ; i < n ; i++)
			liste.add(f[i]);
	}
	/**
	 * Generer le tableau des points
	 */
	private void genererPoints(){
		double angle = 0;
		points= new Point[n+1];
		//Etablir le point centrale au dessus
		points[0] = new Point(pCentral.getXCartesien(),pCentral.getYCartesien(),pCentral.getZCartesien() + haut );
		//Generer des autres points dans la circunference
		for(int i = 1; i <= n; i++){
			double x = pCentral.getXCartesien() + radius * Math.cos(Math.toRadians(angle));
			double y = pCentral.getYCartesien() + radius * Math.sin(Math.toRadians(angle));
			points[i] = new Point(Math.round(x),Math.round(y), pCentral.getZCartesien());
			angle = angle + getAngle();			
		}		
	}
	/**
	 * Creer des facettes a partir du tableau des points.
	 * On commence avec le point au dessus et leur connecte
	 * avec des points a la circunference
	 * @return tableau de facettes
	 */
	private Facette3D[] creerFacettes(){
		Facette3D[] f = new Facette3D[n];	
		//Parcourrir le tableau des points
		for(int i = 0; i < (n-1);i++){
			f[i] = new Facette3D(points[0],points[(i+1)],points[(i+2)]);
		}		
		f[n-1] = new Facette3D(points[0],points[n],points[1]);
		return f;		
	}
	/**
	 * Obtenir le angle avec la complexite du Cone.
	 * @return angle = 360 / nivel de complexite
	 */
	private double getAngle(){
		return 360 / (new Integer(n).doubleValue());
	}
	/**
	 * Obtenir l'Iterator de la liste de Facettes 3D
	 */
	@Override
	public Iterator<Facette3D> getFacettes() {
		// TODO Auto-generated method stub
		return liste.iterator();
	}
	/**
	 * Obtenir le tableau des points au fond du Cone (le trou)
	 * @return
	 */
	public Point[] getHollow(){
		Point[] p = new Point[n];
		for(int i = 1; i <= n ; i++)
			p[i-1] = new Point(points[i]);
		return p;
	}

	/**
	 * Parcourrir tous les points qui form le Trou et
	 * creer une facette avec chaque sommet.
	 */
	@Override
	public void triangulePolygone(Point[] polygone) {
		int i = 0;
		int k = 1;
		for(k=1;k<polygone.length-2;k++)
			liste.add(new Facette3D(polygone[i],polygone[k],polygone[k+1]));
	}

}
